<?php

namespace young\CityDeliver\driver;

use young\CityDeliver\Driver;

class Dada extends Driver
{
    private $app_key = '';
    private $app_secret = '';
    private $source_id = '';
    private $shop_no = '';
    private $city_code = '';
    private $format = 'json';
    private $version = '1.0';
    private $apis = [
      'createOrder'   => '/api/order/addOrder',//新订单
      'relapseOrder'  => '/api/order/reAddOrder',//订单重发
      'queryOrder'    => '/api/order/status/query',//查询订单
      'cancelOrder'   => '/api/order/formalCancel',//取消订单
      'cancelReasons' => '/api/order/cancel/reasons'//取消原因
    ];

    //订单状态
    public $status = [
      1    => '待接单',
      2    => '待取货',
      3    => '配送中',
      4    => '已完成',
      5    => '已取消',
      7    => '已过期',
      8    => '指派单',
      9    => '妥投异常之物品返回中',
      10   => '妥投异常之物品返回完成',
      1000 => '系统故障订单发布失败'
    ];

    const FAIL = "fail";
    const SUCCESS = "success";
    const ORDER_EXIST = 2105;//订单已存在
    const ORDER_EXIST_CANCEL = 2076;//订单已取消

    public function __construct($options)
    {
        $this->gateway = 'http://newopen.qa.imdada.cn';//https://newopen.imdada.cn
        $this->app_key = isset($options['app_key']) ? $options['app_key'] : '';
        $this->app_secret = isset($options['app_secret']) ? $options['app_secret'] : '';
        $this->source_id = isset($options['source_id']) ? $options['source_id'] : '73753';
        $this->shop_no = isset($options['shop_no']) ? $options['shop_no'] : '';
        $this->city_code = isset($options['city_code']) ? $options['city_code'] : '0791';
    }

    //创建新订单
    public function createOrder(array $body)
    {
        $order_no = $body['origin_id'];//商户订单号
        $body['city_code'] = $this->city_code;
        $body['shop_no'] = $this->shop_no;
        $data = $this->request($this->apis['createOrder'], $body);

        if (true === $this->checkSuccess($data)) {
            return $this->returnOrderData([
              'status'     => 1,
              'status_msg' => $this->status[1],
              'distance'   => $data['result']['distance'],
              'price'      => $data['result']['fee']
            ]);
        } elseif ($this->getErrorCode($data) === self::ORDER_EXIST) {
            //订单存在，查询订单详情
            $data = $this->queryOrder($order_no);
            //查询订单成功
            if (true === $this->checkSuccess($data)) {
                $order = $data['result'];
                //如果订单状态=》已取消|已过期|妥投异常
                if (in_array($order['statusCode'], [5, 7, 9, 10])) {
                    //重新发起订单
                    $data = $this->request($this->apis['relapseOrder'], $body);
                    if (true === $this->checkSuccess($data)) {
                        return $this->returnOrderData([
                          'status'     => 1,
                          'status_msg' => $this->status[1],
                          'distance'   => $data['result']['distance'],
                          'price'      => $data['result']['fee']
                        ]);
                    } else {
                        $this->checkError($data);
                    }
                } else {
                    //补单数据
                    return $this->returnOrderData([
                      'status'     => $data['result']['statusCode'],
                      'status_msg' => $data['result']['statusMsg'],
                      'distance'   => $data['result']['distance'],
                      'price'      => $data['result']['actualFee']
                    ]);
                }
            } else {
                $this->checkError($order);
            }
        } else {
            $this->checkError($data);
        }
    }

    /**
     * @name 订单数据返回
     * @param array $data
     * @return array
     */
    private function returnOrderData(array $data)
    {
        $data['distance'] = round($data['distance']);
        return $this->success($data);
    }

    //订单查询
    public function queryOrder($order_no)
    {
        return $this->request($this->apis['queryOrder'], ['order_id' => $order_no]);
    }

    //订单取消
    public function cancelOrder(array $data)
    {
        $order_no = $data['order_no'];//商户订单号
        $body = [
          'order_id'         => $data['order_no'],
          'cancel_reason_id' => $data['cancel_code']
        ];
        $data = $this->request($this->apis['cancelOrder'], $body);
        if (true === $this->checkSuccess($data)) {
            return $this->success(['deduct_fee' => $data['result']['deduct_fee']]);
        } elseif (self::ORDER_EXIST_CANCEL === $this->getErrorCode($data)) {
            //订单已取消，查询订单进行补单
            $data = $this->queryOrder($order_no);
            if ($this->checkSuccess($data)) {
                $deduct_fee = isset($data['result']['deductFee']) ? $data['result']['deductFee'] : 0;
                return $this->success(['deduct_fee' => floatval($deduct_fee)]);
            } else {
                $this->checkError($data);
            }
        } else {
            $this->checkError($data);
        }
    }


    //取消原因
    public function cancelReasons()
    {
        $data = $this->request($this->apis['cancelReasons']);
        $list = [];
        if (true === $this->checkSuccess($data)) {
            foreach ($data['result'] as $item) {
                $list[] = [
                  'id'      => $item['id'],
                  'content' => $item['reason']
                ];
            }
        }
        return $list;
    }

    //抛出异常
    private function checkError($data)
    {
        if (!isset($data['status'])) {
            throw new \Exception('接口异常');
        } elseif ($data['status'] === self::FAIL) {
            throw new \Exception($data['msg']);
        } else {
            throw new \Exception('未知错误');
        }
    }

    //获取错误号
    private function getErrorCode($data)
    {
        if (isset($data['status']) && $data['status'] === self::FAIL) {
            return $data['code'];
        } else {
            throw new \Exception('接口异常');
        }
    }

    //成功
    private function checkSuccess($data)
    {
        return (isset($data['status']) && $data['status'] === self::SUCCESS) ? true : false;
    }

    //接口请求
    private function request($api, $body = '')
    {
        $body = is_array($body) ? json_encode($body, JSON_UNESCAPED_UNICODE) : '';
        $data = [
          'app_key'   => $this->app_key,
          'timestamp' => time(),
          'format'    => $this->format,
          'v'         => $this->version,
          'source_id' => $this->source_id,
          'body'      => $body
        ];
        $signature = $this->sign($data);
        $data['signature'] = $signature;
        return $this->doPost($this->getUrl($api), $data);
    }

    //数据签名
    private function sign(array $data)
    {
        ksort($data);
        $args = '';
        foreach ($data as $key => $value) {
            $args .= $key . $value;
        }
        $args = $this->app_secret . $args . $this->app_secret;
        $sign = strtoupper(md5($args));
        return $sign;
    }

    //验证签名
    public function callback(array $data)
    {
        $signData = [
          'client_id'   => $data['client_id'],
          'order_id'    => $data['order_id'],
          'update_time' => $data['update_time']
        ];
        asort($signData);
        $sign = md5(implode('', $signData));
        return true;
    }
}